﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace MongoScienceDAL.Core.Tests
{
    [TestClass]
    public class CollectionTypeCreationHelperTests
    {
        private Mock<IDataSource> _dataSourceMock;

        private const string CollectionName = "testcollection";
        private const string Username = "testuser";

        [TestInitialize]
        public void TestInit()
        {
            _dataSourceMock = new Mock<IDataSource>();
        }

        public CollectionTypeCreationHelper GetHelper()
        {
            return new CollectionTypeCreationHelper(_dataSourceMock.Object, CollectionName, Username);
        }

        [TestMethod]
        public void CollectionTypeHelperAddTextNormalType()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddText("testfield1", "tf1", "this is a test description", false, false, false, TextTypeEnum.Normal);

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.Text, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(1,type.Settings.Count);
            Assert.IsTrue(type.Settings.ContainsKey("texttype"));
            Assert.AreEqual("normal", type.Settings["texttype"]);
        }

        [TestMethod]
        public void CollectionTypeHelperAddTextLargeType()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddText("testfield1", "tf1", "this is a test description", false, false, false, TextTypeEnum.Large);

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.Text, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(1, type.Settings.Count);
            Assert.IsTrue(type.Settings.ContainsKey("texttype"));
            Assert.AreEqual("large", type.Settings["texttype"]);
        }

        [TestMethod]
        public void CollectionTypeHelperAddTextDropDownType()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddText("testfield1", "tf1", "this is a test description", false, false, false, TextTypeEnum.DropDown);

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.Text, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(1, type.Settings.Count);
            Assert.IsTrue(type.Settings.ContainsKey("texttype"));
            Assert.AreEqual("dropdown", type.Settings["texttype"]);
        }

        [TestMethod]
        public void CollectionTypeHelperAddTValuePlainType()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddValue("testfield1", "tf1", "this is a test description", false, false, false, ValueTypeEnum.Plain, null, null, "##.00");

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.Value, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(2, type.Settings.Count);
            Assert.IsTrue(type.Settings.ContainsKey("valuetype"));
            Assert.AreEqual("plain", type.Settings["valuetype"]);
            Assert.IsTrue(type.Settings.ContainsKey("format"));
            Assert.AreEqual("##.00", type.Settings["format"]);
        }

        [TestMethod]
        public void CollectionTypeHelperAddTValuePlainDropDownType()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddValue("testfield1", "tf1", "this is a test description", false, false, false, ValueTypeEnum.PlainDropDown, null, null,"##.00");

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.Value, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(2, type.Settings.Count);
            Assert.IsTrue(type.Settings.ContainsKey("valuetype"));
            Assert.AreEqual("plaindropdown", type.Settings["valuetype"]);
            Assert.IsTrue(type.Settings.ContainsKey("format"));
            Assert.AreEqual("##.00", type.Settings["format"]);
        }

        [TestMethod]
        public void CollectionTypeHelperAddTValueMeasurementType()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddValue("testfield1", "tf1", "this is a test description", false, false, false, ValueTypeEnum.Measurement, "m", "s","##.00");

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.Value, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(4, type.Settings.Count);
            Assert.IsTrue(type.Settings.ContainsKey("valuetype"));
            Assert.AreEqual("measurement", type.Settings["valuetype"]);
            Assert.IsTrue(type.Settings.ContainsKey("prefix"));
            Assert.AreEqual("m", type.Settings["prefix"]);
            Assert.IsTrue(type.Settings.ContainsKey("unit"));
            Assert.AreEqual("s", type.Settings["unit"]);
            Assert.IsTrue(type.Settings.ContainsKey("format"));
            Assert.AreEqual("##.00", type.Settings["format"]);
        }

        [TestMethod]
        public void CollectionTypeHelperAddValueMeasurementDropDownType()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddValue("testfield1", "tf1", "this is a test description", false, false, false, ValueTypeEnum.MeasurementDropDown, "m", "s", "##.00");

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.Value, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(4, type.Settings.Count);
            Assert.IsTrue(type.Settings.ContainsKey("valuetype"));
            Assert.AreEqual("measurementdropdown", type.Settings["valuetype"]);
            Assert.IsTrue(type.Settings.ContainsKey("prefix"));
            Assert.AreEqual("m", type.Settings["prefix"]);
            Assert.IsTrue(type.Settings.ContainsKey("unit"));
            Assert.AreEqual("s", type.Settings["unit"]);
            Assert.IsTrue(type.Settings.ContainsKey("format"));
            Assert.AreEqual("##.00", type.Settings["format"]);
        }

        [TestMethod]
        public void CollectionTypeHelperAddDate()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddDate("testfield1", "tf1", "this is a test description", false, false, false, false);

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.DateTime, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(1, type.Settings.Count);
            Assert.IsTrue(type.Settings.ContainsKey("datetype"));
            Assert.AreEqual("datetime", type.Settings["datetype"]);
        }

        [TestMethod]
        public void CollectionTypeHelperAddValueSet()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddValueSet("testfield1", "tf1", "this is a test description", 
                               false, false, false, false, true,
                               "tf1","tf5", "testx", "testy", "##.00",true,"test1","test2");

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.ValueSet, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(10, type.Settings.Count);
            Assert.IsTrue(type.Settings.ContainsKey("download"));
            Assert.AreEqual("false", type.Settings["download"]);
            Assert.IsTrue(type.Settings.ContainsKey("graph"));
            Assert.AreEqual("true", type.Settings["graph"]);
            Assert.IsTrue(type.Settings.ContainsKey("xaxis"));
            Assert.AreEqual("tf1", type.Settings["xaxis"]);
            Assert.IsTrue(type.Settings.ContainsKey("yaxis"));
            Assert.AreEqual("tf5", type.Settings["yaxis"]);
            Assert.IsTrue(type.Settings.ContainsKey("xaxislabel"));
            Assert.AreEqual("testx", type.Settings["xaxislabel"]);
            Assert.IsTrue(type.Settings.ContainsKey("yaxislabel"));
            Assert.AreEqual("testy", type.Settings["yaxislabel"]);
            Assert.IsTrue(type.Settings.ContainsKey("format"));
            Assert.AreEqual("##.00", type.Settings["format"]);
            Assert.IsTrue(type.Settings.ContainsKey("measurement"));
            Assert.AreEqual("true", type.Settings["measurement"]);
            Assert.IsTrue(type.Settings.ContainsKey("unit"));
            Assert.AreEqual("test1", type.Settings["unit"]);
            Assert.IsTrue(type.Settings.ContainsKey("prefix"));
            Assert.AreEqual("test2", type.Settings["prefix"]);
        }

        [TestMethod]
        public void CollectionTypeHelperAddFiles()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddFiles("testfield1", "tf1", "this is a test description", false, false, false);

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.Files, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(0, type.Settings.Count);
        }

        [TestMethod]
        public void CollectionTypeHelperAddVersionedFile()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddVersionedFile("testfield1", "tf1", "this is a test description", false, false, false);

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.VersionedFile, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(0, type.Settings.Count);
        }

        [TestMethod]
        public void CollectionTypeHelperAddParentLink()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddParentLink("testfield1", "tf1", "this is a test description", false, false, false, "testCollection");

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.ParentLink, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(1, type.Settings.Count);
            Assert.IsTrue(type.Settings.ContainsKey("collection"));
            Assert.AreEqual("testCollection", type.Settings["collection"]);
        }

        [TestMethod]
        public void CollectionTypeHelperAddChildLinks()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddChildLinks("testfield1", "tf1", "this is a test description", false, false, false, "testCollection");

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.ChildLinks, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(1, type.Settings.Count);
            Assert.IsTrue(type.Settings.ContainsKey("collection"));
            Assert.AreEqual("testCollection", type.Settings["collection"]);
        }

        [TestMethod]
        public void CollectionTypeHelperAddBoolean()
        {
            //setup
            var helper = GetHelper();
            var type = new ScienceType();
            _dataSourceMock.Setup(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>())).Callback<string, ScienceType>((source, scienceType) => type = scienceType);

            //execute
            helper.AddBoolean("testfield1", "tf1", "this is a test description", false, false, false);

            //verfiy
            _dataSourceMock.Verify(x => x.AddCollectionType(CollectionName, It.IsAny<ScienceType>()), Times.Once());

            Assert.AreEqual("testfield1", type.Name);
            Assert.AreEqual("tf1", type.Key);
            Assert.AreEqual("this is a test description", type.Description);
            Assert.AreEqual(ScienceTypeEnum.Boolean, type.Type);
            Assert.AreEqual(0, type.Index);
            Assert.AreEqual(false, type.Required);
            Assert.AreEqual(false, type.Hidden);
            Assert.AreEqual(DateTime.Today.Day, type.CreatedOn.Day);
            Assert.AreEqual(Username, type.CreatedBy);

            Assert.AreEqual(0, type.Settings.Count);
        }
    }
}
